
/* Author: Habeeb
 *
 * This file realises the interactions between the all the characters
 *
 * This file is an interface to the controller of the system. When the controller
 * realises that 2 people come into contact, ir-regardless of whoever, an interaction 
 * call will be invoked
 *
 * This is a static class, i.e. no objects of this class 
 * need(s) to be created outside of the class
 */

function Interactions(){
 	//console.log('the Interactions class has been instantiated');
}


/*
 *  These are the kind of events that can take place:
 * 
 * 	-> fight(s) between the rebels and army personnel (y)
 *  -> casual interactions between the NPC and player (influence the view) (depends on the NPC and player)
 *  -> casual interactions between the rebels and the citizens (y)
 *	-> casual interactions between citizens (y)
 *	-> casual interactions between army personnel (no)
 *  -> spies can talk to the merchants (no)
 *	-> spies can report status to the army (no)
 *	-> purchase of arms by the army or rebels  from the merchants (no)
 *	-> a merchant can get killed if caught during the act of selling arms to rebels (hold...)
 *
 * 	IMPORTANT NOTE: Each interaction function will invoke its own rule, 
 *	i.e. when 2 persons interact what type of event that will be
 */


/* This function is invoked by the controller to determine the type of event
 * that would occur between 2 character(s) (be it player or NPC's)
 * The inputs can be any generic object as long as they contain their getType()
 * if the 2 objects to passed in is a player, pass in the first object as a player and the second as 
 * the other object
 */
Interactions.determineTypeOfEvent = function(Object1, Object2){

	// I will check the type of 1 object and invoke the corresponding function to perform further checks 
	switch(Object1.getType()) {

		case 'Rebel':
            Interactions.rebelInteractions(Object1, Object2);
			break;

		case 'Army':
            Interactions.armyInteractions(Object1, Object2);
			break;

		case 'Merchant':
            Interactions.merchantInteractions(Object1, Object2);
			break;

		case 'Spy':
            Interactions.spyInteractions(Object1, Object2);
			break;

		case 'Citizen':
            Interactions.citizenInteractions(Object1, Object2);
			break;

		case 'Player':
            Interactions.playerInteractions(Object1, Object2);
			break;
	}// switch case statement

};


// This function defines all the interactions a rebel can have
Interactions.rebelInteractions = function(rebelObject, interactingObject){

	switch(interactingObject.getType()) { 
		// This means a rebel is tag teaming, need to decide what to do (for now nothing)
		case 'Rebel':
			//console.log('a rebel tag team interaction is on going');
			// Two rebels are talking
			rebelObject.eventType = interactingObject.eventType = "two_rebels_talking";
            rebelObject.updateSprite(rebelObject.eventType);
            interactingObject.updateSprite(interactingObject.eventType);
			// Right now dunnoe what needs to be done
			break;

		// Since this interaction is among 1 rebel and 1 army, the interaction should be fighting 
		// (but there is no infuence on them directly, however the surrounding objects are affected within a radius of 10 grids)
		case 'Army':
			//console.log('an army personnel and rebel are fighting');
			rebelObject.eventType = interactingObject.eventType = "fighting";

            // Update the sprites
            rebelObject.updateSprite(rebelObject.eventType);
            interactingObject.updateSprite(interactingObject.eventType);

            // Update the probability for surrounding objects
            var winner = Interactions.determineWhoIsWinningTheFight(interactingObject, rebelObject);
            if(winner == "Army"){
                probDistribution.calculateRadialDistribution(arrayOfSurroundingObjects, interactingObject);
                interactingObject.fitness = Interactions.wrapTheFitnessValue(interactingObject.fitness + 10);
                interactingObject.currentFightOutcome = "won";
                interactingObject.eventOutcomeQueue.push("won");
                rebelObject.currentFightOutcome = "lost";
            } else {
                probDistribution.calculateRadialDistribution(arrayOfSurroundingObjects, rebelObject);
                rebelObject = Interactions.wrapTheFitnessValue(rebelObject.fitness - 10);
                rebelObject.currentFightOutcome = "won";
                rebelObject.eventOutcomeQueue.push("won");
                interactingObject.currentFightOutcome = "lost";
            }


			break;

		// The interaction is between a rebel and merchant, indicating sale of arms
		case 'Merchant':
			//console.log('a rebel is purchasing arms from the merchant');
			// Update for the rebel first
			rebelObject.eventType = "purchasing";

			// Update for the merchant now
			interactingObject.eventType = "sale";
			interactingObject.updateSprite(interactingObject.eventType);

			// Perform the interaction
			Interactions.performWeaponsSale(rebelObject);
			// Now update the sprite type which will reflect the correct weapon colour in the sprite
			rebelObject.updateSprite(rebelObject.eventType);
			break;

		// Should not happen
		case 'Spy':
			alert('a rebel is talking to a spy and this should not happen');
			break;

		// This is the case where the rebel is influencing the citizen
		case 'Citizen':
			//console.log('a rebel is influencing a citizen');

			// Update the event for the rebel to influencing
			rebelObject.eventType = "influencing";
			interactingObject.eventType = "being_influenced";
            rebelObject.updateSprite(rebelObject.eventType);
            interactingObject.updateSprite(interactingObject.eventType);

			// Calculate the probability of success of the outcome
			probDistribution.calculateProbBasedOnSingleObject(rebelObject, interactingObject);
			break;	
	}// switch case statement

};

// This function defines all the interactions an army personnel can have
Interactions.armyInteractions = function(armyObject, interactingObject){

	switch(interactingObject.getType()) { 
		// This is a fighting event
		case 'Rebel':
			armyObject.eventType = interactingObject.eventType = "fighting";
            armyObject.updateSprite(armyObject.eventType);
            interactingObject.updateSprite(interactingObject.eventType);

            // Update the probability for the surrounding objects
            var winner = Interactions.determineWhoIsWinningTheFight(armyObject, interactingObject);
            if(winner == "Army"){
                probDistribution.calculateRadialDistribution(arrayOfSurroundingObjects, armyObject);
                armyObject.fitness = Interactions.wrapTheFitnessValue(armyObject.fitness + 10);
                armyObject.currentFightOutcome = "won";
                armyObject.eventOutcomeQueue.push("won");
                interactingObject.currentFightOutcome = "lost";
            } else {
                probDistribution.calculateRadialDistribution(arrayOfSurroundingObjects, interactingObject);
                interactingObject.fitness = Interactions.wrapTheFitnessValue(interactingObject.fitness - 10);
                interactingObject.currentFightOutcome = "won";
                interactingObject.eventOutcomeQueue.push("won");
                armyObject.currentFightOutcome = "lost";
            }

			break;

		case 'Merchant':
			armyObject.eventType = "purchasing";
			interactingObject.eventType = "sale";
			interactingObject.updateSprite(interactingObject.eventType);
			Interactions.performWeaponsSale(armyObject);
			// So that the sprite will be updated correctly
			armyObject.updateSprite(armyObject.eventType);
			break;

	}// switch case statement

};

// This funcition defines all the interactions a merchant can have
Interactions.merchantInteractions = function(merchantObject, interactingObject){

	switch(interactingObject.getType()) { 
		case 'Rebel':
			merchantObject.eventType = "sale";
			merchantObject.updateSprite(merchantObject.eventType);
			interactingObject.eventType = "purchasing";
			interactingObject.updateSprite(interactingObject.eventType);
			Interactions.performWeaponsSale(interactingObject);
			break;
		
		case 'Army':
			merchantObject.eventType = "sale";
			merchantObject.updateSprite(merchantObject.eventType);
			interactingObject.eventType = "purchasing";
			Interactions.performWeaponsSale(interactingObject);
			// So that the sprite will be updated correctly
			interactingObject.updateSprite(interactingObject.eventType);
			break;
	}// switch case statement

};

// This function defines all the interactions a spy can have
Interactions.spyInteractions = function(spyObject, interactingObject){

	switch(interactingObject.getType()) { 
		case 'Citizen':
			spyObject.eventType = "influencing";
            spyObject.updateSprite(spyObject.eventType);
			interactingObject.eventType = "being_influenced";
            interactingObject.updateSprite(interactingObject.eventType);
			probDistribution.calculateProbBasedOnSingleObject(spyObject, interactingObject);
			break;
	}// switch case statement

};

// This function defines the interactions citizens can have
Interactions.citizenInteractions = function(citizenObject, interactingObject){

	switch(interactingObject.getType()) { 
		case 'Rebel':
			citizenObject.eventType = "being_influenced";
            citizenObject.updateSprite(citizenObject.eventType);
			interactingObject.eventType = "influencing";
            interactingObject.updateSprite(interactingObject.eventType);
			probDistribution.calculateProbBasedOnSingleObject(interactingObject, citizenObject);
			break;

		case 'Spy':
			citizenObject.eventType = "being_influenced";
            citizenObject.updateSprite(citizenObject.eventType);
			interactingObject.eventType = "influencing";
            interactingObject.updateSprite(interactingObject.eventType);
			probDistribution.calculateProbBasedOnSingleObject(interactingObject, citizenObject);
			break;

	}// switch case statement

};


// This function is responsible for the player interactions and 
// it will just invoke the responsible interactions function
Interactions.playerInteractions = function(playerObject, interactingObject){

	var localInteractingObjectType = null;

	switch (playerObject.career){
		// The player is a rebel, so invoke rebel interactions (the player is always a rebel)
		case 'Rebel':
			Interactions.playerRebelInteractions(playerObject, interactingObject);// this has been changed, the player can only be a rebel
			break;

	}

};


// This function takes care of the interactions of the player who is a rebel and is interacting with another object
Interactions.playerRebelInteractions = function(playerObject, interactingObject){

	// While the player is still interacting with the object we need to update the correct sprites	
	switch(interactingObject.getType()){
		// Rebel talking to army
		case 'Army':
		Interactions.playerTalkingToArmy(playerObject, interactingObject);
		break;

		// Rebel talking to merchant
		case 'Merchant':
		Interactions.playerTalkingToMerchant(playerObject, interactingObject);
		break;

		// Rebel talking to spy
		case 'Spy':
		Interactions.playerTalkingToSpy(playerObject, interactingObject);
		break;

		// Rebel talking to citizen
		case 'Citizen':
		Interactions.playerTalkingToCitizen(playerObject, interactingObject);
		break;

	}// switch case statement
};

// This function defines all the interactions between a player(who is a rebel) and an army personnel
// army has an id of 2
Interactions.playerTalkingToArmy = function(playerObject, armyObject){

	// Check if the conversation is still happening
	 if (conv_type == "Army"){
		switch(playerObject.currentDialogue){

			// The player will fight the army
			case "I want to fight you":
				msg.text_queue(conv_type, "I will to fight you");
				playerObject.eventType = armyObject.eventType = "fighting";
				// Update the sprites
				armyObject.updateSprite(armyObject.eventType);
				// Update the probability for surrounding objects
				var winner = Interactions.determineWhoIsWinningTheFight(armyObject, playerObject);
				if(winner == "Army"){
					probDistribution.calculateRadialDistribution(arrayOfSurroundingObjects, interactingObject);
					armyObject.fitness = Interactions.wrapTheFitnessValue(armyObject.fitness + 10);
					armyObject.currentFightOutcome = "won";
                    //playerObject.currentFightOutcome = "lost";
				} else {
					probDistribution.calculateRadialDistribution(arrayOfSurroundingObjects, playerObject);
					playerObject = Interactions.wrapTheFitnessValue(playerObject.fitness - 10);
                    armyObject.currentFightOutcome = "lost";
					playerObject.currentFightOutcome = "won";
				}
				break;

			case "I do not want to fight you":
				msg.text_queue(conv_type, "I am also not interested in fighting");
				break;

			case "Go away":
				msg.text_queue(conv_type, "You too GET LOST!");
				break;
		}//switch case statement
	
	}//while loop
};


// This function defines all the interactions between a player(who is a rebel) and a merchant
// merchant has an id of 3
Interactions.playerTalkingToMerchant = function(playerObject, merchantObject){

	if (conv_type == "Merchant"){

		switch(playerObject.currentDialogue){
			case "Do not want to purchase weapon":
				msg.text_queue(conv_type, "Ok buy next time");
				break;

			case "I want to purchase a weapon":
				msg.text_queue(conv_type, "Here is your weapon");
				console.log('a rebel is purchasing arms from the merchant');
				// Update for the rebel first
				playerObject.eventType = "purchasing";

				// Update for the merchant now
				merchantObject.eventType = "sale";
				merchantObject.updateSprite(merchantObject.eventType);

				// Perform the interaction
				Interactions.performWeaponsSale(playerObject);
				// Now update the sprite type which will reflect the correct weapon colour in the sprite
				playerObject.updateSprite(playerObject.eventType);
				break;
		}//switch case statement

	}//while loop

};


// This function defines all the interactions between a player(who is a rebel) and a spy
// spy has an id of 4
Interactions.playerTalkingToSpy = function(playerObject, spyObject){

	if (conv_type == "Spy"){
		switch(playerObject.currentDialogue){
			case "Join me dude":
				msg.text_queue(conv_type, "You join me dude");
				break;
			case "Your government is not helping you":
				msg.text_queue(conv_type, "They are helping, you should join us");
				break;
		}
	}//while loop
};


// This function defines all the interactions between a player(who is a rebel) and a spy
// spy has an id of 4
Interactions.playerTalkingToBlackMarket = function(playerObject){
    if (conv_type == "blackMarket"){
        switch(playerObject.currentDialogue){
            case "20 Guns, your asshole":
                var success = Math.floor(2*Math.random()); // 50%
                if (success <=1) {
                    rebel_weapons+= 20;
                    msg.text_queue(conv_type, "Here you are, sir");
                } else {
                    msg.text_queue(conv_type, "No Way!");
                }
                break;
            case "Your government is not helping you":
                msg.text_queue(conv_type, "Go away dog!");
                break;
        }
    }//while loop
};

// This function defines all the interactions between a player(who is a rebel) and a spy
// spy has an id of 4
Interactions.playerTalkingToTVStation = function(playerObject){

    if (conv_type == "tvStation2"){
        switch(playerObject.currentDialogue){
            case "War is Evil!":
                var success = Math.floor(5*Math.random()); // 20%
                if (success <=1) {
                    rebel_control += 0.05;
                    army_control -= 0.05;
                    msg.text_queue(conv_type, "I agree with you");
                } else {
                    msg.text_queue(conv_type, "Go away dog!");
                }
                break;
            case "Don't cheated by those politicians":
                var success = Math.floor(4*Math.random()); // 25%
                if (success <=1) {
                    rebel_control += 0.05;
                    army_control -= 0.05;
                    msg.text_queue(conv_type, "Understood");
                } else {
                    msg.text_queue(conv_type, "Go away dog!");
                }

                break;
            case "War or Death?":
                var success = Math.floor(10*Math.random()); // 10%
                if (success <=1) {
                    rebel_control += 0.05;
                    army_control -= 0.05;
                    msg.text_queue(conv_type, "...");
                } else {
                    msg.text_queue(conv_type, "Go away dog!");
                }
                break;
        }
    }//while loop
};


// This function defines all the interactions between a player(who is a rebel) and a citizen
// citizen has an id of 5
Interactions.playerTalkingToCitizen = function(playerObject, citizenObject){

	var isTryingToInfluence = false;
	if (conv_type == "Citizen"){
		switch(playerObject.currentDialogue){
			case "Do not join the war":
			isTryingToInfluence = true;
			break;
			case "Listen to me":
			isTryingToInfluence = true;
			break;
			case "The government is screwed up":
			isTryingToInfluence = true;
			break;
			default:
			isTryingToInfluence = false;
			break;
		}

		// Check and see what is the influence status
		if(isTryingToInfluence){
			// Update the event for the rebel to influencing
			playerObject.eventType = "influencing";
			citizenObject.eventType = "being_influenced";
			playerObject.updateSprite(playerObject.eventType);
			citizenObject.updateSprite(citizenObject.eventType);

			// Calculate the probability of success of the outcome
			probDistribution.calculateProbBasedOnSingleObject(playerObject, citizenObject);

			// Check if the probability is more than 0.5
			if(citizenObject.rateAtWhichCanBeInfluenced > 0.8){
				msg.text_queue(conv_type, "I am totally into you");
			} else if(citizenObject.rateAtWhichCanBeInfluenced > 0.5){
				msg.text_queue(conv_type, "I like your speech");
			}

		// The rebel is not influencing the citizen
	} else {
			//console.log('No influencing is happening');
		}

	}//while loop
};


// This function will determine the type of object the player is going to interact with
Interactions.determineTypeOfObjectPlayerIsInteractingWith = function(interactingObject){

	switch(interactingObject.getType()){
		
		case 'Rebel': 		return "rebel";
		
		case 'Army': 		return "army";
		
		case 'Merchant': 	return "merchant";

		case 'Spy': 		return "spy";

		case 'Citizen': 	return "citizen";

	}//switch case statement
};


// This function will determine who is winning the fight among the rebel and army personnel 
// by checking the weaponType which is an integer
Interactions.determineWhoIsWinningTheFight = function(armyObject, rebelObject){

	// Determine who has better weapons and is stronger
	var localArmyWeaponType  = armyObject.weaponType;
	var localRebelWeaponType = rebelObject.weaponType;

	// If the weapons are of same type, then need to perform fitness check
	// which is stimulated by the rateOfInfluence
	if(localArmyWeaponType == localRebelWeaponType){

		if(armyObject.fitness < rebelObject.fitness){
			return rebelObject.getType();
		} else if(armyObject.fitness > rebelObject.fitness){
			return armyObject.getType();
		} else {
			// This is a special sitiuation where all their skills are equal,
			// then just flip a coin and return
			var randNo = Math.random();
			if(randNo > 0.5){
				return rebelObject.getType();
			}else {
				return armyObject.getType();
			}
		}
	
	// They both dont have the same weapon
	} else {
		
		if(localArmyWeaponType > localRebelWeaponType){
			return armyObject.getType();
		} else {
			return rebelObject.getType();
		}
	}

};

// This function set the weapon, according to the colour of weapon purchased, 
// the weapon type is an integer
Interactions.performWeaponsSale = function(thisObjectToAffect){
	switch(thisObjectToAffect.weaponType){
		case 0:
			thisObjectToAffect.weaponType = 1;
			break;
		case 1:
			thisObjectToAffect.weaponType = 2;
			break;
		case 2:
			thisObjectToAffect.weaponType = 3;
			break;
		case 3:
			thisObjectToAffect.weaponType = 4;
			break;
		case 4:
			thisObjectToAffect.weaponType = 4;
			//console.log(thisObjectToAffect.getType() + ' has already purchased the best possible weapon');
			break;
	}//switch case statement
    thisObjectToAffect.eventOutcomeQueue.push(1);

};

// This function will wrap the values to be between 0 and 100 for the fitness level
Interactions.wrapTheFitnessValue = function(thisValue){
	if(thisValue > 100){
		thisValue = 100;
	} else if(thisValue < 0){
		thisValue = 0;
	} else {
		// no change
	}
	return thisValue;
};
